---
import ResponsiveToggle from './ResponsiveToggle.astro'
import { DarkMode } from 'accessible-astro-components'
import { Image } from 'astro:assets'
import logo from '../assets/img/logo.svg'
---

<div id="main-navigation" class="is-desktop py-8">
  <div class="container">
    <a href="/" class="flex items-center gap-2 !no-underline">
      <Image src={logo} alt="Your Logo" width="47" height="37" />
      <span class="font-bold">Accessible Astro</span>
    </a>
    <div class="wrapper">
      <nav class="desktop-menu" aria-label="Main navigation desktop">
        <ul class="menu">
          <slot />
        </ul>
      </nav>
      <DarkMode />
      <ResponsiveToggle />
    </div>
    <nav class="mobile-menu" aria-label="Main navigation mobile">
      <ul class="menu">
        <slot />
      </ul>
    </nav>
  </div>
</div>

<script>
  document.addEventListener('astro:page-load', () => {
    // variables
    const mainNav = document.querySelector('#main-navigation')
    const mainMenu = mainNav.querySelector('ul')
    const dropdownMenus = [...document.querySelectorAll('.has-dropdown button')]

    // functions
    const setActiveMenuItem = () => {
      const mobileDesktopMenus = mainNav.querySelectorAll('nav > ul')
      const currenPathname = window.location.pathname

      mobileDesktopMenus.forEach((menu) => {
        const menuItems = [...menu.querySelectorAll('a:not([rel*="external"])')] as HTMLAnchorElement[]

        menuItems.forEach((menuItem) => {
          if (currenPathname.includes(menuItem.pathname.replaceAll('/', '')) && menuItem.textContent !== 'Home') {
            menuItem.classList.add('is-active')
            menuItem.setAttribute('aria-current', 'page')
          } else if (menuItem.textContent === 'Home' && currenPathname === '/') {
            menuItem.classList.add('is-active')
            menuItem.setAttribute('aria-current', 'page')
          }
        })
      })
    }

    const checkMenuSize = () => {
      const mainNavWidth = mainNav.getBoundingClientRect().width
      const desktopMenuWidth = document.querySelector('.desktop-menu').getBoundingClientRect().width
      const logoWidthBuffer = 300
      const totalMenuWidth = Math.round(desktopMenuWidth) + logoWidthBuffer

      if (totalMenuWidth >= mainNavWidth) {
        mainNav.classList.remove('is-desktop')
        mainNav.classList.add('is-mobile')
      } else if (totalMenuWidth <= mainNavWidth) {
        mainNav.classList.add('is-desktop')
        mainNav.classList.remove('is-mobile')
      }
    }

    const isOutOfViewport = (element) => {
      const elementBounds = element.getBoundingClientRect()
      return elementBounds.right > (window.innerWidth || document.documentElement.clientWidth)
    }

    const openDropdownMenu = (dropdownMenu) => {
      const dropdownList = dropdownMenu.parentNode.querySelector('ul')

      dropdownMenu.classList.add('show')
      dropdownMenu.setAttribute('aria-expanded', 'true')

      if (isOutOfViewport(dropdownList)) {
        dropdownList.style.left = 'auto'
      }
    }

    const closeDropdownMenu = (dropdownMenu) => {
      dropdownMenu.classList.remove('show')
      dropdownMenu.setAttribute('aria-expanded', 'false')
    }

    const closeAllDropdownMenus = () => {
      for (let i = 0; i < dropdownMenus.length; i++) {
        closeDropdownMenu(dropdownMenus[i])
      }
    }

    const toggleDropdownMenu = (event) => {
      if (event.target.getAttribute('aria-expanded') === 'false') {
        closeAllDropdownMenus()
        openDropdownMenu(event.target)
      } else {
        closeDropdownMenu(event.target)
      }
    }

    // execution
    mainMenu &&
      mainMenu.addEventListener('keydown', (event) => {
        const element = event.target as Element
        const currentMenuItem = element.closest('li')
        const menuItems = [...mainMenu.querySelectorAll('.menu-item')]
        const currentDropdownMenu = element.closest('.has-dropdown button')
        const currentDropdownMenuItem = element.closest('.has-dropdown li')
        const currentIndex = menuItems.findIndex((item) => item === currentMenuItem)

        const key = event.key
        let targetItem

        if (key === 'ArrowRight') {
          if (menuItems.indexOf(currentMenuItem) === menuItems.length - 1) {
            targetItem = menuItems[0]
          } else {
            targetItem = menuItems[currentIndex + 1]
          }
        }

        if (key === 'ArrowLeft') {
          if (menuItems.indexOf(currentMenuItem) === 0) {
            targetItem = menuItems[menuItems.length - 1]
          } else {
            targetItem = menuItems[currentIndex - 1]
          }
        }

        if (key === 'Escape') {
          targetItem = menuItems[0]
        }

        if (currentDropdownMenu) {
          const firstDropdownItem = currentDropdownMenu.nextElementSibling.querySelector('li')

          if (key === 'ArrowDown') {
            event.preventDefault()
            openDropdownMenu(currentDropdownMenu)
            targetItem = firstDropdownItem
          }

          if (key === 'Escape') {
            closeDropdownMenu(currentDropdownMenu)
          }
        }

        if (currentDropdownMenuItem) {
          const currentDropdownList = currentDropdownMenuItem.parentNode
          const dropdownMenuItems = [...currentDropdownList.querySelectorAll('li')]
          const currentIndex = dropdownMenuItems.findIndex((item) => item === currentDropdownMenuItem)

          if (key === 'ArrowDown') {
            event.preventDefault()

            if (dropdownMenuItems.indexOf(currentDropdownMenuItem as HTMLLIElement) === dropdownMenuItems.length - 1) {
              targetItem = dropdownMenuItems[0]
            } else {
              targetItem = dropdownMenuItems[currentIndex + 1]
            }
          }

          if (key === 'ArrowUp') {
            event.preventDefault()

            if (dropdownMenuItems.indexOf(currentDropdownMenuItem as HTMLLIElement) === 0) {
              targetItem = dropdownMenuItems[dropdownMenuItems.length - 1]
            } else {
              targetItem = dropdownMenuItems[currentIndex - 1]
            }
          }

          if (key === 'Escape') {
            const currentDropdownMenu = (currentDropdownList as Element).previousElementSibling
            targetItem = currentDropdownMenu.parentNode
            closeAllDropdownMenus()
          }

          if (key === 'Tab') {
            const currentDropdownMenu = (currentDropdownList as Element).previousElementSibling

            if (dropdownMenuItems.indexOf(currentDropdownMenuItem as HTMLLIElement) === dropdownMenuItems.length - 1) {
              closeDropdownMenu(currentDropdownMenu)
            }
          }
        }

        if (targetItem) {
          targetItem.querySelector('a, button, input').focus()
        }
      })

    dropdownMenus &&
      dropdownMenus.forEach((dropdownMenu) => {
        dropdownMenu.addEventListener('click', toggleDropdownMenu)
      })

    setActiveMenuItem()
    checkMenuSize()

    window.addEventListener('resize', checkMenuSize)
    window.addEventListener('click', (event) => {
      const element = event.target as Element
      if (!element.hasAttribute('aria-haspopup') && !element.classList.contains('submenu-item')) {
        closeAllDropdownMenus()
      }
    })
  })
</script>

<style lang="scss" is:global>
  @use '../assets/scss/base/breakpoint' as *;
  @use '../assets/scss/base/outline' as *;

  #main-navigation {
    > .container {
      display: flex;
      justify-content: space-between;
      flex-wrap: wrap;
    }

    &.is-desktop {
      .desktop-menu {
        visibility: visible;
        position: static;
      }

      .mobile-menu {
        display: none;
      }

      .darkmode-toggle {
        margin-top: -6px;
      }
    }

    &.is-mobile {
      flex-direction: column;

      .mobile-menu {
        display: none;

        &.show {
          display: block;
        }
      }

      .desktop-menu {
        visibility: hidden;
        z-index: -99;
        position: absolute;
        left: 0;
      }

      .responsive-toggle {
        display: block;
      }
    }

    .wrapper {
      display: flex;
      align-items: center;
      gap: 1rem;
    }

    nav {
      > ul {
        display: flex;
        gap: 1.5rem;
        list-style-type: none;

        a,
        button {
          text-decoration: none;
          font-size: 1.125rem;
          line-height: 1.6875rem;
        }

        a:hover,
        a:focus,
        .is-active,
        .has-dropdown > button:hover,
        .has-dropdown > button:focus {
          text-decoration: underline;
          text-decoration-thickness: 1px;
          text-decoration-style: wavy;
          text-underline-offset: 7px;
        }

        .is-active {
          font-weight: bold;
        }
      }
    }

    .mobile-menu {
      flex-basis: 100%;
      padding: 2rem 0;

      > ul {
        flex-direction: column;

        ul {
          position: relative;
          margin-top: 1rem;
        }
      }

      a,
      button {
        display: block;
        width: 100%;
        padding: 0.5rem 0;
      }
    }

    .has-dropdown {
      position: relative;

      > button {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        padding: 0;
        margin-top: -1px;
        border: none;
        color: var(--action-color);

        &:hover {
          color: var(--action-color-state);

          &::after {
            border-color: var(--action-color-state);
          }
        }

        &::after {
          content: '';
          width: 0.85rem;
          height: 0.75em;
          margin-top: -0.25rem;
          border-style: solid;
          border-width: 0.2em 0.2em 0 0;
          border-color: var(--action-color);
          transform: rotate(135deg);
        }

        &.show {
          &::after {
            margin-top: 0.25rem;
            transform: rotate(-45deg);
          }

          ~ ul {
            display: flex;
            flex-direction: column;
            gap: 1rem;
          }
        }
      }

      ul {
        display: none;
        position: absolute;
        z-index: 100;
        min-width: 260px;
        top: 125%;
        right: 0;
        bottom: auto;
        left: 0;
        padding: 1rem;
        background-color: var(--neutral-background);
        border: 2px solid black;
        box-shadow: 0 10px 20px rgba(0, 0, 0, 0.15);
      }
    }
  }

  .darkmode-toggle {
    padding: 0;
    border: none;

    svg {
      width: 30px;
      margin-top: 4px;
    }

    svg path {
      fill: var(--action-color);
    }

    &:hover {
      svg path {
        fill: var(--action-color-state);
      }
    }

    &:focus {
      @include outline;

      &:not(:focus-visible) {
        outline: none;
        box-shadow: none;
      }
    }
  }
</style>
